import 'dart:async';
import 'dart:io';
import 'package:path_provider/path_provider.dart';
import 'package:baselib/utils/log_util.dart';
import 'package:framelib/config/api_config.dart';
import 'package:nim_core/nim_core.dart';
import 'package:get/get.dart';
typedef chatRoomHandler = void Function(CustomNotification event);

class NIMSDKUtil{
  static final NIMSDKUtil _singleton = NIMSDKUtil._internal();
  static NIMSDKUtil get instance => NIMSDKUtil();
  factory NIMSDKUtil() {
    return _singleton;
  }
  NIMSDKUtil._internal();

  final subsriptions = <StreamSubscription>[];
  var authSubscription;
  var messageSubscription;
  var chatroomEventNotifYSubscription;
  var chatroomMessageReceivedSubsription;
  var chatroomMessageStatusSubscription;
  var messageStatusSubscription;
  var systemCustomNotificationSubscription;


  init() async{
    /// 监听的、事件
    authSubscription = NimCore.instance.authService.authStatus.listen((event) {
      LogUtil.d('NIMSDKUtil---->authStatus event=${event?.toString()}');
      if (event is NIMKickOutByOtherClientEvent) {
        /// 监听到被踢事件
        LogUtil.d('NIMSDKUtil---->authStatus 监听到被踢事件 event ,clientType=${event?.clientType}'
            ',customClientType=${event?.customClientType},status=${event?.status}');
      } else if (event is NIMAuthStatusEvent) {
        /// 监听到其他事件
        LogUtil.d('NIMSDKUtil---->authStatus 监听到其他事件 event ,status=${event?.status}');
      }else if (event is NIMDataSyncStatusEvent) {
        LogUtil.d('NIMSDKUtil---->authStatus 监听到数据同步事件 event ,status=${event?.status}');
        /// 监听到数据同步事件
        if (event.status == NIMAuthStatus.dataSyncStart) {
          /// 数据同步开始
          LogUtil.d('NIMSDKUtil---->authStatus 数据同步开始 event ,status=${event?.status}');
        } else if (event.status == NIMAuthStatus.dataSyncFinish) {
          /// 数据同步完成
          LogUtil.d('NIMSDKUtil---->authStatus 数据同步完成 event ,status=${event?.status}');
        }
      }
    });
    messageStatusSubscription = await NimCore.instance.messageService.onMessageStatus.listen((NIMMessage message) {
      LogUtil.d('NIMSDKUtil---->onMessageStatus event=${message?.toMap()}');
      // 1、根据sessionId判断是否是自己的消息
      // 2、更改内存中消息的状态
      // 3、刷新界面
    });
    //普通消息监听
    messageSubscription = await NimCore.instance.messageService.onMessage.listen((List<NIMMessage> list) {
      LogUtil.d('NIMSDKUtil---->onMessage event=${list?.map((e) => e?.toMap())?.toList()}');
      // 处理新收到的消息，为了上传处理方便，SDK 保证参数 messages 全部来自同一个聊天对象。
    });

    NIMSDKOptions options;
    if (Platform.isAndroid) {
      final directory = await getExternalStorageDirectory();
      options = NIMAndroidSDKOptions(
        appKey: ApiConfig.wyyx_app_key,
        shouldSyncStickTopSessionInfos: true,
        sdkRootDir: directory != null ? '${directory.path}/NIMAndroidFlutter' : null
      );
    } else if (Platform.isIOS) {
      final directory = await getApplicationDocumentsDirectory();
      options = NIMIOSSDKOptions(
        appKey: ApiConfig.wyyx_app_key,
        shouldSyncStickTopSessionInfos: true,
        sdkRootDir: '${directory.path}/NIMIOSFlutter',
      );
    }
    await NimCore.instance.initialize(options).then((result){
      LogUtil.d('NIMSDKUtil---->initialize-->初始化result=${result}');
      if (result.isSuccess) {
        /// 初始化成功
        LogUtil.d('initialize-->初始化成功');
      } else {
        /// 初始化失败
        LogUtil.d('initialize-->初始化失败');
      }
    });
  }


  ///聊天室消息监听
  onChatroomServiceMessageReceivedListen(Function(List<NIMChatroomMessage>) onChatroomServiceMessageReceivedListener){
    //聊天室消息监听
    chatroomMessageReceivedSubsription = NimCore.instance.chatroomService.onMessageReceived
        .listen((List<NIMChatroomMessage> messages) {
      LogUtil.d('NIMSDKUtil---->chatroomService.onMessageReceived messages=${messages?.map((e) => e?.toMap())?.toList()}');

      messages.forEach((message) {
        // message.messageType  messageDirection  sessionId: 3746464776
        NIMMessageAttachment messageAttachment = message.messageAttachment;
        if(messageAttachment!=null){
          var messageAttachmentmap = messageAttachment.toMap();
          print('NIMSDKUtil---->chatroomService.onMessageReceived messageAttachmentmap=${messageAttachmentmap}');
        }
        print('NIMSDKUtil---->chatroomService.onMessageReceived message=${message?.toMap()}');
        print('NIMSDKUtil,ChatroomService##on message received: ${message.fromAccount},${message.fromNickname},${message.content}');
      });
      //添加到评论区
      if(onChatroomServiceMessageReceivedListener!=null)onChatroomServiceMessageReceivedListener(messages);
    });
  }
  ///事件通知
  onChatroomServiceEventNotifiedListen(Function(NIMChatroomEvent) onChatroomServiceEventNotifiedListener){
    chatroomEventNotifYSubscription = NimCore.instance.chatroomService.onEventNotified.listen((event) {
      LogUtil.d('NIMSDKUtil---->onEventNotified event=${event?.toMap()}');
      // if (event is NIMChatroomStatusEvent) {
      //   /// 连接状态事件通知
      // }else if (event is NIMChatroomKickOutEvent) {
      //   /// 离开事件通知
      //   nimChatroomKickOutEvent.value = event;
      // }
      if(onChatroomServiceEventNotifiedListener!=null)onChatroomServiceEventNotifiedListener(event);
    });
  }
  ///系统通知
  onCustomNotificationListen(Function(CustomNotification) onCustomNotificationListener){
    systemCustomNotificationSubscription = NimCore.instance.systemMessageService.onCustomNotification.listen((CustomNotification event) {
      LogUtil.d('NIMSDKUtil--->  inviteOnMic onCustomNotification--->event=${event?.toMap()}');
      if(onCustomNotificationListener!=null)onCustomNotificationListener(event);
    });
  }
  ///事件通知
  onChatroomServiceMessageStatusChangedListen(Function(NIMChatroomMessage) onChatroomServiceMessageStatusChangedListenListener){
    chatroomMessageStatusSubscription = NimCore.instance.chatroomService.onMessageStatusChanged.listen((NIMChatroomMessage message) {
      LogUtil.d('NIMSDKUtil---->onMessageStatusChanged event=${message?.toMap()}');
      // if(message.sessionId ){
      //
      // }
      // 1、根据sessionId判断是否是自己的消息
      // 2、更改内存中消息的状态
      // 3、刷新界面
      if(onChatroomServiceMessageStatusChangedListenListener!=null)onChatroomServiceMessageStatusChangedListenListener(message);
    });
    NimCore.instance.chatroomService.onMessageAttachmentProgressUpdate.listen((NIMAttachmentProgress progress) {
      LogUtil.d('NIMSDKUtil---->onMessageAttachmentProgressUpdate progress=${progress?.toMap()}');
      // if(message.sessionId ){
      //
      // }
      // 1、根据sessionId判断是否是自己的消息
      // 2、更改内存中消息的状态
      // 3、刷新界面
    });
  }
  void onAddHandler(Function handler) {
    // systemNotifyHandlers.add(handler);
  }

  void onRemoveHandler(Function handler) {
    // systemNotifyHandlers.remove(handler);
  }
  /**
   * 登录
   */
  Future<NIMResult<void>> login({account,token})async{
    final loginResult = await NimCore.instance.authService.login(
        NIMLoginInfo(account: account, token: token,)
    );
    if (loginResult.isSuccess) {
      /// 登录成功
      LogUtil.d('云信登录成功-->loginResult=${loginResult?.toMap()}');
    }
    return loginResult;
  }
  /**
   * 登出
   */
  Future<NIMResult<void>> logout({account,token})async{
    final logoutResult = await NimCore.instance.authService.logout();
    if (logoutResult.isSuccess) {
      /// 登出成功
      LogUtil.d('云信登出成功');
    }
    return logoutResult;
  }
  /********************************************单聊********************************/
  //发送消息
  Future<NIMResult<NIMMessage>> sendMessage(NIMMessage data) async{
    return await NimCore.instance.messageService.sendMessage(message: data);
  }
  //创建文本消息 以单聊类型为例 NIMSessionType.p2p
  Future<NIMResult<NIMMessage>> createTextMessage(String account,NIMSessionType sessionType,String text,) async{
    var result = MessageBuilder.createTextMessage(
        sessionId: account, sessionType: sessionType??NIMSessionType.p2p, text: text);
    return result;
  }
  //创建图片消息 以单聊类型为例 NIMSessionType.p2p
  Future<NIMResult<NIMMessage>> createImageMessage(
      String account,NIMSessionType sessionType,String filePath,int fileSize,
      {String displayName, NIMNosScene nosScene = NIMNosScenes.defaultIm}) async{
    var result = MessageBuilder.createImageMessage(
        sessionId: account, sessionType: sessionType??NIMSessionType.p2p,
        filePath: filePath,
        fileSize: fileSize,
        displayName: displayName,
        nosScene: nosScene
    );
    return result;
  }
  //创建语音消息 以单聊类型为例 NIMSessionType.p2p
  Future<NIMResult<NIMMessage>> createAudioMessage(
      String account,NIMSessionType sessionType,String filePath,int fileSize,int duration,
      {NIMNosScene nosScene = NIMNosScenes.defaultIm}) async{
    var result = MessageBuilder.createAudioMessage(
        sessionId: account, sessionType: sessionType??NIMSessionType.p2p,
        filePath: filePath,
        fileSize: fileSize,
        duration: duration,
        nosScene: nosScene
    );
    return result;
  }
  //创建视频消息 以单聊类型为例 NIMSessionType.p2p
  Future<NIMResult<NIMMessage>> createVideoMessage(
      String account,NIMSessionType sessionType,String filePath, int duration,
       int width, int height, String displayName,
      {int fileSize,NIMNosScene nosScene = NIMNosScenes.defaultIm}) async{
    var result = MessageBuilder.createVideoMessage(
        sessionId: account,
        sessionType: sessionType??NIMSessionType.p2p,
        filePath: filePath,
        fileSize: fileSize,
        duration: duration,
        width: width,
        height: height,
        displayName: displayName,
        nosScene: nosScene
    );
    return result;
  }
  //创建文件消息 以单聊类型为例 NIMSessionType.p2p
  Future<NIMResult<NIMMessage>> createFileMessage(
      String account,NIMSessionType sessionType,String filePath,String displayName,
      {int fileSize,NIMNosScene nosScene = NIMNosScenes.defaultIm}) async{
    var result = MessageBuilder.createFileMessage(
        sessionId: account,
        sessionType: sessionType??NIMSessionType.p2p,
        filePath: filePath,
        fileSize: fileSize,
        displayName: displayName,
        nosScene: nosScene
    );
    return result;
  }
  //创建地理位置消息 以单聊类型为例 NIMSessionType.p2p
  Future<NIMResult<NIMMessage>> createLocationMessage(
      String account,NIMSessionType sessionType, double latitude,
       double longitude,
       String address) async{
    var result = MessageBuilder.createLocationMessage(
        sessionId: account,
        sessionType: sessionType??NIMSessionType.p2p,
        latitude: latitude,
        longitude: longitude,
        address: address
    );
    return result;
  }
  //手动下载多媒体资源示
  Future<NIMResult<void>> downloadAttachment(NIMMessage message,{bool thumb})async{
    var result = await NimCore.instance.messageService.downloadAttachment(message: message, thumb: thumb??true);
    return result;
  }

  Future<NIMResult<List<NIMMessage>>> queryMessageList(
      String account, NIMSessionType sessionType, int limit)async{
    var result = await NimCore.instance.messageService.queryMessageList(account,sessionType,limit);
    return result;
  }
  /********************************************聊天室********************************/
  Future<List<NIMChatroomMember>> fetchChatroomMembers(String roomId, int limit,{
     NIMChatroomMemberQueryType queryType,
    String lastMemberAccount,
  })async{
    List<NIMChatroomMember> chatRoomMembers=[];

    NIMResult<List<NIMChatroomMember>> allNormalMemberResult = await NimCore.instance.chatroomService.fetchChatroomMembers(
      roomId: roomId,
      queryType: queryType??NIMChatroomMemberQueryType.onlineNormalMember,
      limit: limit??10,
    );
    if(allNormalMemberResult?.isSuccess){
      var results = allNormalMemberResult.data??[];
      if(results.isNotEmpty){
        chatRoomMembers.addAll(results);
      }
    }
    NIMResult<List<NIMChatroomMember>> onlineGuestMemberByEnterTimeDescResult = await NimCore.instance.chatroomService.fetchChatroomMembers(
      roomId: roomId,
      queryType: queryType??NIMChatroomMemberQueryType.onlineGuestMemberByEnterTimeDesc,
      limit: limit??10,
    );
    if(onlineGuestMemberByEnterTimeDescResult?.isSuccess){
      var results = onlineGuestMemberByEnterTimeDescResult.data??[];
      if(results.isNotEmpty){
        chatRoomMembers.addAll(results);
      }
    }
    //     .then((result) {
    //   var index = 0;
    //   result.data?.forEach((member) {
    //     print(
    //         'ChatroomService fetchChatroomMembers ##member_${index++}: ${member.account} ${member.nickname} ${member.memberType}');
    //   });
    // });
    return chatRoomMembers;
  }
  Future<NIMResult<List<NIMChatroomMember>>> fetchChatroomMembersByAccounts(String roomId, List<String> accountList,)async{
    NIMResult<List<NIMChatroomMember>> result = await NimCore.instance.chatroomService.fetchChatroomMembersByAccount(
      roomId: roomId,
      accountList: accountList,
    );
    if(result?.isSuccess){

    }
      //   .then((result) {
      var index = 0;
      result.data?.forEach((member) {
        print(
            'NIMSDKUtil,getMembers ##member_${index++}: ${member.account} ${member.nickname} ${member.memberType}');
      });
    // });
    return result;
  }

  ///查询云端历史消息
  Future<NIMResult<List<NIMChatroomMessage>>> fetchMessageHistory({
    String roomId,int startTime,int limit,List<NIMMessageType> messageTypeList})async{
    NIMResult<List<NIMChatroomMessage>> fetchMsg = await NimCore.instance.chatroomService.fetchMessageHistory(
      roomId: roomId,
      startTime: startTime??DateTime.now().millisecondsSinceEpoch,
      limit: limit??10,
      direction: QueryDirection.QUERY_OLD,
      messageTypeList: messageTypeList??[NIMMessageType.text],
    );
    // fetchMsg.data?.forEach((message) {
    //   print(
    //       'ChatroomService##message history: ${index++} ${message.fromAccount} ${message.fromNickname} '
    //           '\'${message.content}\'');
    //
    // });
    return fetchMsg;
    // .then((messages) {
    //   var index = 0;
    //   messages.data?.forEach((message) {
    //     print(
    //         'ChatroomService##message history: ${index++} ${message.fromAccount} ${message.fromNickname} '
    //             '\'${message.content}\'');
    //   });
    // });
  }
  //进入聊天室，注意：文档上面NIMChatroomEnterRequest 的room的"r"为大写，所以要注意大小写
  Future<NIMResult<NIMChatroomEnterResult>> enterChatroom({
        String roomId,String nickname,String avatar,})async{
    var  enterChatroomResult = await  NimCore.instance.chatroomService.enterChatroom(
      NIMChatroomEnterRequest(
        roomId: roomId,
        nickname: nickname,
        avatar: avatar,
        retryCount: 3,
      ),
    );
    if (enterChatroomResult.isSuccess) LogUtil.d('加入聊天室成功');
    return enterChatroomResult;
  }
  ///退出聊天室
  Future<NIMResult<void>> exitChatroom({String roomId})async{
    var exitChatroomResult = await NimCore.instance.chatroomService.exitChatroom(roomId);
    return exitChatroomResult;
  }
  ///创建文本消息
  Future<NIMResult<NIMChatroomMessage>> createChatroomTextMessage({
      String roomId,String text,})async{
    NIMResult<NIMChatroomMessage> createResult = await ChatroomMessageBuilder.createChatroomTextMessage(
      roomId: roomId, text: text,);
    LogUtil.d('roomId-->${roomId}');
    return createResult;
  }
  ///创建音频消息
  Future<NIMResult<NIMChatroomMessage>> createChatroomAudioMessage({
    String roomId,String filePath,int duration,NIMNosScene nosScene = NIMNosScenes.defaultIm
  })async{
    var createResult = await ChatroomMessageBuilder.createChatroomAudioMessage(
      roomId: roomId, filePath: filePath,duration: duration,nosScene: nosScene);
    return createResult;
  }
  ///创建自定义消息
  Future<NIMResult<NIMChatroomMessage>> createChatroomCustomMessage({
    String roomId,NIMMessageAttachment attachment
  })async{
    var createResult = await ChatroomMessageBuilder.createChatroomCustomMessage(
        roomId: roomId, attachment: attachment);
    return createResult;
  }
  ///创建图片消息
  Future<NIMResult<NIMChatroomMessage>> createChatroomImageMessage({
    String roomId,String filePath,String displayName,
    NIMNosScene nosScene = NIMNosScenes.defaultIm
  })async{
    var createResult = await ChatroomMessageBuilder.createChatroomImageMessage(
        roomId: roomId, filePath: filePath,displayName: displayName,
      nosScene: nosScene);
    return createResult;
  }
  ///创建地理位置信息
  Future<NIMResult<NIMChatroomMessage>> createChatroomLocationMessage({
    String roomId,double latitude,double longitude,String address
  })async{
    var createResult = await ChatroomMessageBuilder.createChatroomLocationMessage(
        roomId: roomId,latitude: latitude,longitude: longitude,address: address);
    return createResult;
  }
  ///创建文件消息
  Future<NIMResult<NIMChatroomMessage>> createChatroomFileMessage({
    String roomId,String filePath,String displayName,
    NIMNosScene nosScene = NIMNosScenes.defaultIm
  })async{
    var createResult = await ChatroomMessageBuilder.createChatroomFileMessage(
        roomId: roomId,filePath: filePath,displayName: displayName,nosScene: nosScene);
    return createResult;
  }
  ///创建视频消息
  Future<NIMResult<NIMChatroomMessage>> createChatroomVideoMessage({
    String roomId,String filePath,int duration,int width,int height,
    String displayName,NIMNosScene nosScene = NIMNosScenes.defaultIm
  })async{
    var createResult = await ChatroomMessageBuilder.createChatroomVideoMessage(
        roomId: roomId,filePath: filePath,duration: duration,width: width,height: height,
        displayName: displayName,nosScene: nosScene);
    return createResult;
  }
  ///创建提醒消息
  Future<NIMResult<NIMChatroomMessage>> createChatroomTipMessage({String roomId})async{
    var createResult = await ChatroomMessageBuilder.createChatroomTipMessage(roomId: roomId);
    return createResult;
  }
  ///发送聊天室消息
  Future<NIMResult<NIMChatroomMessage>> sendChatroomMessage({
              NIMChatroomMessage message,bool enableHistory})async{
    //该消息是否要保存到服务器，
    message?.enableHistory = (enableHistory??true);
    var sendResult = await NimCore.instance.chatroomService.sendChatroomMessage(message);
    return sendResult;
  }

  ///获取聊天室信息
  Future<NIMResult<NIMChatroomInfo>> fetchChatroomInfo({String roomId}) async{
    // LogUtil.d('fetchChatroomInfo--->roomId=${roomId}');
    var chatroomInfo = await NimCore.instance.chatroomService.fetchChatroomInfo(roomId);
    if(chatroomInfo.isSuccess){
      LogUtil.d('fetchChatroomInfo--->${chatroomInfo?.data?.name}');
    }else{
      LogUtil.d('fetchChatroomInfo--->${chatroomInfo?.errorDetails}');
    }

    return chatroomInfo;
  }
  ///修改聊天室信息
  Future<NIMResult<void>> updateChatroomInfo({
    String roomId,NIMChatroomUpdateRequest request,bool needNotify})async{
    var updateChatroomInfoResult = await NimCore.instance.chatroomService.updateChatroomInfo(
      roomId: roomId,
      request: request??NIMChatroomUpdateRequest(
        announcement: '修改群公告',
      ),
      needNotify: needNotify??true,
    );
    return updateChatroomInfoResult;
  }

  ///修改聊天室本人信息
  Future<NIMResult<void>> updateChatroomMyMemberInfo({
    String chatroomId,String nickname,String avatar,})async{
    var updateChatroomMyMemberInfoResult = await NimCore.instance.chatroomService
        .updateChatroomMyMemberInfo(
      roomId: chatroomId,
      request: NIMChatroomUpdateMyMemberInfoRequest(
        avatar: avatar,
        nickname: nickname,
        needSave: true,
      ),
    );
    return updateChatroomMyMemberInfoResult;
  }
  ///设置、取消管理员
  Future<NIMResult<NIMChatroomMember>> markChatroomMemberBeManager({
        bool isAdd,String roomId,String account})async{
    var markChatroomMemberBeManagerResult = await NimCore.instance.chatroomService
          .markChatroomMemberBeManager(
      isAdd: isAdd??true,
      options: NIMChatroomMemberOptions(
        roomId: roomId,
        account: account,
      ),
    );
    return markChatroomMemberBeManagerResult;
  }
  ///添加、移除普通成员
  Future<NIMResult<NIMChatroomMember>> markChatroomMemberBeNormal({
    bool isAdd,String roomId,String account}) async{
    var result = await NimCore.instance.chatroomService
        .markChatroomMemberBeNormal(
      isAdd: isAdd??true,
      options: NIMChatroomMemberOptions(
        roomId: roomId,
        account: account,
      ),
    );
    return result;
  }
  ///添加、移除黑名单用户
  Future<NIMResult<NIMChatroomMember>> markChatroomMemberInBlackList({
    bool isAdd,String roomId,String account}) async{
    var result = await NimCore.instance.chatroomService
        .markChatroomMemberInBlackList(
      isAdd: isAdd??true,
      options: NIMChatroomMemberOptions(
        roomId: roomId,
        account: account,
      ),
    );
    return result;
  }
  ///添加、移除禁言用户
  Future<NIMResult<NIMChatroomMember>> markChatroomMemberMuted({
    bool isAdd,String roomId,String account}) async{
    var result = await NimCore.instance.chatroomService
        .markChatroomMemberMuted(
      isAdd: isAdd??true,
      options: NIMChatroomMemberOptions(
        roomId: roomId,
        account: account,
      ),
    );
    return result;
  }
  ///踢出成员
  Future<NIMResult<void>> kickChatroomMember({
    String roomId,String account}) async{
    var result = await NimCore.instance.chatroomService.kickChatroomMember(
       NIMChatroomMemberOptions(
        roomId: roomId,
        account: account,
      ),
    );
    return result;
  }
  ///临时禁言成员
  Future<NIMResult<void>> markChatroomMemberTempMuted({
    int duration,String roomId,String account}) async{
    var result = await NimCore.instance.chatroomService.markChatroomMemberTempMuted(
      //禁言时长,单位毫秒
      duration: duration??10 * 1000,
      options: NIMChatroomMemberOptions(
        roomId: roomId,
        account: account,
      ),
    );
    return result;
  }
}
